
import { PATH_MODE } from "../common/pathMode.js";
import { _curve } from './curve.js'
import { _circle, _circles } from "./canvas.js";
import { rayMix } from '../math/arrayMix.js';
import { _o } from '../math/index.js';
import { toMatrix } from '../math/array.js';
import { linkPoints, stripPoints, stripLoopPoints, stripFanPoints } from '../algorithm/link.js'
import { _traversal } from '../algorithm/traversal.js'

// 点
export const _points = (ctx, { points }, props) => {
    let r = 3
    points.forEach((t, i) => {
        _circle(ctx, t, r, {
            stroke: 'none',
            fill: 'red',
            ...props
        })
    });
}

export const _lineStrip = (ctx, { points, curve }) => {
    _curve(ctx, { points, curve })
}

export const _lineLoop = (ctx, { points, curve }) => {
    _curve(ctx, { points, curve, loop: true })
}
// 线段
export const _lines = (ctx, { points, curve }) => {
    _curve(ctx, { points, curve, step: 2, discrete: true })
}
// 多边形
export const _ploygon = (ctx, { points, n, curve }) => {
    let matrix = toMatrix(points, n)
    matrix.forEach(ps => {
        _curve(ctx, { points: ps, curve, loop: true })
    })
}
// 三角形
export const _triangles = (ctx, { points, curve }) => {
    return _ploygon(ctx, { points, n: 3, curve })
}


const _serial = (ctx, { points, n, loop, curve }) => {
    let iter = (ps) => {
        return _curve(ctx, { points: ps, curve, loop: true })
    }
    return _traversal({
        points,
        n,
        iter,
        loop
    })
}

const _triangleSerial = (ctx, { points, curve }) => {
    let n = 3
    let loop = false
    return _serial(ctx, { points, n, loop, curve })
}
const _squareSerial = (ctx, { points, curve }) => {
    let n = 4
    let loop = false
    return _serial(ctx, { points, n, loop, curve })
}

const _triangleSerialLoop = (ctx, { points, curve }) => {
    let n = 3
    let loop = true
    return _serial(ctx, { points, n, loop, curve })
}
const _squareSerialLoop = (ctx, { points, curve }) => {
    let n = 4
    let loop = true
    return _serial(ctx, { points, n, loop, curve })
}

const _triangleStrip = (ctx, { points, curve }) => {
    let matrix = stripPoints(points, 3)
    matrix.forEach(ps => {
        _curve(ctx, { points: ps, curve, loop: true })
    })
}

const _triangleStripLoop = (ctx, { points, curve }) => {
    let matrix = stripLoopPoints(points, 3)
    matrix.forEach(ps => {
        _curve(ctx, { points: ps, curve, loop: true })
    })
}
const _triangleFan = (ctx, { points, curve }) => {
    let matrix = stripFanPoints(points, 2)
    let last = matrix.pop()
    matrix.forEach(ps => {
        _curve(ctx, { points: ps, curve })
    })
    _curve(ctx, { points: last, curve, loop: true })
}


// 四边形
export const _squares = (ctx, { points, curve }) => {
    return _ploygon(ctx, { points, n: 4, curve })
}

const _squareStrip = (ctx, { points, curve }) => {
    let matrix = stripPoints(points, 4)
    matrix.forEach(ps => {
        _curve(ctx, { points: ps, curve, loop: true })
    })
}

const _squareStripLoop = (ctx, { points, curve }) => {
    let matrix = stripLoopPoints(points, 4)
    matrix.forEach(ps => {
        _curve(ctx, { points: ps, curve, loop: true })
    })
}
// 扇线
const _lineFan = (ctx, { points, curve }) => {
    let [p, ...rest] = points
    let ps = rayMix(p, rest)
    _curve(ctx, { points: ps, curve })
}


export const _ray = (ctx, { points, curve }) => {
    let o = _o(points)
    let ps = rayMix(o, points)
    _curve(ctx, { points: ps, curve, step: 2 })
}

const _rayOne = (ctx, { points, curve }) => {
    let o = _o(points)
    _curve(ctx, { points: [o, points[0]], curve })
}


const _rayFan = (ctx, { points, curve }) => {
    return _ray(ctx, { points, curve }) + _lineLoop(ctx, { points, curve })
}
const _link = (ctx, { points, curve }) => {
    let lps = linkPoints(points)
    _curve(ctx, { points: lps, curve, step: 2 })
}
const pathModeMapFn = {
    [PATH_MODE.LINE_STRIP]: _lineStrip,
    [PATH_MODE.LINE_LOOP]: _lineLoop,
    [PATH_MODE.POINTS]: _points,
    [PATH_MODE.LINES]: _lines,
    [PATH_MODE.TRIANGLES]: _triangles,
    [PATH_MODE.TRIANGLE_SERIAL]: _triangleSerial,
    [PATH_MODE.TRIANGLE_SERIAL_LOOP]: _triangleSerialLoop,
    [PATH_MODE.SQUARES]: _squares,
    [PATH_MODE.LINE_FAN]: _lineFan,
    [PATH_MODE.RAY]: _ray,
    [PATH_MODE.RAY_FAN]: _rayFan,
    [PATH_MODE.LINK]: _link,
    [PATH_MODE.TRIANGLE_STRIP]: _triangleStrip,
    [PATH_MODE.SQUARE_STRIP]: _squareStrip,
    [PATH_MODE.TRIANGLE_STRIP_LOOP]: _triangleStripLoop,
    [PATH_MODE.SQUARE_STRIP_LOOP]: _squareStripLoop,
    [PATH_MODE.SQUARE_SERIAL]: _squareSerial,
    [PATH_MODE.SQUARE_SERIAL_LOOP]: _squareSerialLoop,
    [PATH_MODE.TRIANGLE_FAN]: _triangleFan

}

export const _pathMode = (ctx, { pathMode, points, curve, closed }, props) => {
    if (closed && !pathMode) {
        pathMode = PATH_MODE.LINE_LOOP
    }
    let fn = pathModeMapFn[pathMode] || _lineStrip
    fn(ctx, { points, curve })
    let { stroke, fill, fillRule } = props
    if (fill !== 'none') {
        if (fillRule === 'evenodd') {
            ctx.fill('evenodd')
        } else {
            ctx.fill()
        }
    }
    if (stroke == null || stroke !== 'none') {
        ctx.stroke()
    }
}